﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Bettzueche.RLLibrary.Types;

namespace RLProject1.UnitTest
{
    [TestClass]
    public class MultiTilingTest
    {
        MultiTiling GetMultiTiling1() {
            int tilingsCount = 4;
            double precision = 0.2;
            double min = 0.0;
            double max = 2.0;
            MultiTiling tilings = new MultiTiling(tilingsCount, precision, min, max);
            return tilings;
        }

        MultiTiling GetMultiTiling2() {
            int tilingsCount = 4;
            double precision = 0.2;
            double min = -4.0;
            double max = -2.0;
            MultiTiling tilings = new MultiTiling(tilingsCount, precision, min, max);
            return tilings;
        }

        [TestMethod]
        public void MultiTiling_GetFeatureNumbers1() {
            double testVal = 0.51;
            int[] expectedArr = { 0, 2, 4, 6 };
            var tilings = GetMultiTiling1();
            int[] fNums = null;

            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            Assert.IsNotNull(fNums);
            Assert.AreEqual(4, fNums.Length, "Number of features not the expected one.");
            for (int i = 0; i < fNums.Length; i++) {
                Assert.AreEqual(expectedArr[i], fNums[i], "unexpexted feature number");
            }
        }

        [TestMethod]
        public void MultiTiling_GetFeatureNumbers2() {
            double testVal = 0.8; // eine Intervallgrenze. Erwartet: Min incl., Max excl.
            int[] expectedArr = { 1, 2, 5, 6 };
            var tilings = GetMultiTiling1();
            int[] fNums = null;

            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            Assert.IsNotNull(fNums);
            Assert.AreEqual(4, fNums.Length, "Number of features not the expected one.");
            for (int i = 0; i < fNums.Length; i++) {
                Assert.AreEqual(expectedArr[i], fNums[i], "unexpexted feature number");
            }
        }

        [TestMethod]
        public void MultiTiling_GetFeatureNumbersMinMax() {
            double testVal = 0.0; // = Min
            int[] expectedArr = { 0, 4 };
            var tilings = GetMultiTiling1();
            int[] fNums = null;

            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            Assert.IsNotNull(fNums);
            Assert.AreEqual(2, fNums.Length, "Number of features not the expected one.");
            for (int i = 0; i < fNums.Length; i++) {
                Assert.AreEqual(expectedArr[i], fNums[i], "unexpexted feature number");
            }

            testVal = 2.0; // = Max
            expectedArr = new int[0];
            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            Assert.IsNotNull(fNums);
            Assert.AreEqual(0, fNums.Length, "Number of features not the expected one.");
        }

        [TestMethod]
        public void MultiTiling_GetFeatureNumbersNegativeRange() {
            double testVal = -4.0 + 0.51;
            int[] expectedArr = { 0, 2, 4, 6 };
            var tilings = GetMultiTiling2();
            int[] fNums = null;

            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            Assert.IsNotNull(fNums);
            Assert.AreEqual(4, fNums.Length, "Number of features not the expected one.");
            for (int i = 0; i < fNums.Length; i++) {
                Assert.AreEqual(expectedArr[i], fNums[i], "unexpexted feature number");
            }
        }

        //[TestMethod]
        //public void MultiTiling_GetFeatureSet() {

        //}

        [TestMethod]
        public void MultiTiling_GetMediansInt() {
            double testVal = 0.51;
            int[] expectedKeyArr = { 0, 2, 4, 6 };
            double[] expectedValueArr = { 0.4, 0.6, 0.2, 0.8};
            var tilings = GetMultiTiling1();
            int[] fNums = null;
            Dictionary<int, double> fMedians = null;
            try {
                fNums = tilings.GetFeatureNumbers(testVal);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetFeatureNumbers(double)");
                return;
            }
            try {
                fMedians = tilings.GetMedians(fNums);
            }
            catch (Exception e) {
                Assert.Fail(e.ToString() + " at performing GetMedians(int[])");
                return;
            }
            Assert.IsNotNull(fMedians);
            Assert.AreEqual(4, fMedians.Count, "Number of medians not the expected one.");
            int[] keyArr = new int[fMedians.Count];
            double[] valueArr = new double[fMedians.Count];
            int arrIdx = 0;
            foreach (var key in fMedians.Keys) {
                keyArr[arrIdx] = key;
                valueArr[arrIdx] = fMedians[key];
                arrIdx++;
            }
            Array.Sort(keyArr);
            for (int i = 0; i < keyArr.Length; i++) {
                Assert.AreEqual<int>(expectedKeyArr[i], keyArr[i], "unexpexted feature number");
            }
            double delta = 0.01;
            for (int i = 0; i < expectedValueArr.Length; i++) {
                Assert.AreEqual(expectedValueArr[i], fMedians[expectedKeyArr[i]], delta);
            }

        }

    }
}
